package com.skyline.jfs.storage.service.impl;

import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.skyline.jfs.cluster.model.JFSNode;
import com.skyline.jfs.common.config.Config;
import com.skyline.jfs.namespace.dao.JFSDirectoryDao;
import com.skyline.jfs.namespace.dao.JFSFileDao;
import com.skyline.jfs.namespace.model.JFSDirectory;
import com.skyline.jfs.namespace.model.JFSFile;
import com.skyline.jfs.storage.dao.JFSStorageDao;
import com.skyline.jfs.storage.exception.FileAllReadyExistException;
import com.skyline.jfs.storage.exception.FileNameUncorrectException;
import com.skyline.jfs.storage.model.JFSAbsoluteStorage;
import com.skyline.jfs.storage.service.Commander;

@Service("commander")
public class CommanderImpl extends UnicastRemoteObject implements Commander {

	private JFSFileDao jfsFileDao;

	private JFSDirectoryDao jfsDirectoryDao;
	
	private JFSStorageDao jfsStorageDao;

	public CommanderImpl() throws RemoteException, MalformedURLException {
		super();
	}

	public JFSFileDao getJfsFileDao() throws RemoteException {
		return jfsFileDao;
	}

	public void setJfsFileDao(JFSFileDao jfsFileDao) throws RemoteException {
		this.jfsFileDao = jfsFileDao;
	}

	public JFSDirectoryDao getJfsDirectoryDao() throws RemoteException {
		return jfsDirectoryDao;
	}

	public void setJfsDirectoryDao(JFSDirectoryDao jfsDirectoryDao) throws RemoteException {
		this.jfsDirectoryDao = jfsDirectoryDao;
	}

	private static final long serialVersionUID = 1L;

	@Override
	public List<String> getJFSNodeToStore(int size) throws RemoteException {
		List<JFSNode> clusterNodes = Config.getClusterNodes();
		List<String> jfsNodeIp = new ArrayList<String>();
		int normalNodeCount = 0;
		for (normalNodeCount = 0; normalNodeCount < clusterNodes.size(); normalNodeCount++) {
			if (clusterNodes.get(normalNodeCount).getActivity().equals("ERROR")) {
				break;
			}
		}
//		for(int i=0;i<100;i++)
//		 System.out.println("normalNodeCount:"+clusterNodes.size());
		int maxSize = normalNodeCount;
		if (normalNodeCount >= size) {
			maxSize = size;
		}
		for (int i = 0; i < maxSize; i++) {
			jfsNodeIp.add(clusterNodes.get(i).getIp());
		}
		return jfsNodeIp;
	}

	@Override
	public void invalidJFSNode(Integer id) throws RemoteException {
		List<JFSNode> clusterNodes = Config.getClusterNodes();
		for (int i = 0; i < clusterNodes.size(); i++) {
			JFSNode node = clusterNodes.get(i);
			if (node.getId().equals(id)) {
				node.setActivity("ERROR");
				clusterNodes.remove(i);
				clusterNodes.add(node);
				break;
			}
		}

	}

	@Override
	public void invalidJFSNode(String ip) throws RemoteException {
		List<JFSNode> clusterNodes = Config.getClusterNodes();
		for (int i = 0; i < clusterNodes.size(); i++) {
			JFSNode node = clusterNodes.get(i);
			if (node.getIp().equals(ip)) {
				node.setActivity("ERROR");
				clusterNodes.remove(i);
				clusterNodes.add(node);
				break;
			}
		}
	}

	@Override
	public void consumeStorage(Integer id, Long storeConsume) throws RemoteException {
		List<JFSNode> clusterNodes = Config.getClusterNodes();
		for (int i = 0; i < clusterNodes.size(); i++) {
			JFSNode node = clusterNodes.get(i);
			if (node.getId().equals(id)) {
				node.setUsableSpace(node.getUsableSpace() - storeConsume);
				break;
			}
		}
	}

	@Override
	public void consumeStorage(String ip, Long storeConsume) throws RemoteException {
		List<JFSNode> clusterNodes = Config.getClusterNodes();
		for (int i = 0; i < clusterNodes.size(); i++) {
			JFSNode node = clusterNodes.get(i);
			if (node.getIp().equals(ip)) {
				node.setUsableSpace(node.getUsableSpace() - storeConsume);
				break;
			}
		}
	}

	public long createFile(String path, long size, int replicNum) throws RemoteException {
		JFSFile file = jfsFileDao.findFileByDir(path);
		if (file != null) {
			//同名文件存在，不能保存
			String exceptionMessage="The file "+path+" all ready exists. Please check and retry!";
			FileAllReadyExistException exception =new FileAllReadyExistException(exceptionMessage);
			throw exception;
		} else {
			String dirPath = "/";
			String[] dirs = path.split("/");
			for (int i = 1; i < dirs.length - 1; i++) {
				String dir = dirs[i];
				if (dir.equals("") || dir.equals(" ")) {
					continue;
				}
				JFSDirectory jfsDir = jfsDirectoryDao.findDirByDir(dirPath);
				Long parent = jfsDir.getId();
				dirPath += (dir + "/");
				jfsDir = jfsDirectoryDao.findDirByDir(dirPath);
				if (jfsDir == null) {
					jfsDirectoryDao.insertDir(parent, dirPath, dir, 2);
				}
			}
			JFSDirectory parentDir = jfsDirectoryDao.findDirByDir(dirPath);
			String fileName = dirs[dirs.length - 1];
			if (fileName.equals(" ")||path.substring(path.length()-1, path.length()).equals("/")) {
				// 输入的文件名不正确，因而不能够保存；
				String exceptionMessage ="The filename "+path+" is uncorrect!";
				FileNameUncorrectException exception =new FileNameUncorrectException(exceptionMessage);
				throw exception;
			} else {
				jfsFileDao.insertFile(parentDir.getId(), fileName, path, size, replicNum, 2);
				JFSFile insertedFile = jfsFileDao.findFileByDir(path);
				return insertedFile.getId();
			}
		}
	}

	@Override
	public List<String> getAbsoluteFilePath(String fileName) throws RemoteException {
		JFSFile jfsFile=jfsFileDao.findFileByDir(fileName);
		Long fileId=jfsFile.getId();
		List<JFSAbsoluteStorage> storages=jfsStorageDao.findJFSAbsoluteStorageByFileID(fileId);
		List<String> absoluteFilePaths=new ArrayList<String>();
		for(int i=0;i<storages.size();i++){
			absoluteFilePaths.add(storages.get(i).getAbsoluteFilePath());
		}
		return absoluteFilePaths;
	}
	
	public List<Integer> getFileStoreJFSNodeID(String fileName) throws RemoteException {
		// TODO Auto-generated method stub
		return null;
	}
	
	public JFSStorageDao getJfsStorageDao()  throws java.rmi.RemoteException{
		return jfsStorageDao;
	}

	public void setJfsStorageDao(JFSStorageDao jfsStorageDao) throws java.rmi.RemoteException {
		this.jfsStorageDao = jfsStorageDao;
	}

}
